package com.dman.multi.algo;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import com.dman.multi.core.Section;

public class BalancedSectionAlgo extends MaxSectionAlgo{
	
	private static int MAX_SECTIONS;
	private static int MAX_CONCURRENT_SOCKETS;
	private boolean foundNumSections;
	private static Map<Long, Integer> maxSizeToSections = new LinkedHashMap<Long, Integer>();
	static{
		long unitSize = 1 << 20;
		maxSizeToSections.put(0L, 8);
		maxSizeToSections.put(unitSize, 12);
		maxSizeToSections.put(unitSize << 4, 16);
		maxSizeToSections.put(unitSize << 6, 20);
		maxSizeToSections.put(unitSize << 8, 24);
		maxSizeToSections.put(unitSize << 10, 28);
		maxSizeToSections.put(unitSize << 12, 32);
		/*maxSizeToSections.put(unitSize << 5, 20);
		maxSizeToSections.put(unitSize << 6, 24);
		maxSizeToSections.put(unitSize << 7, 28);
		maxSizeToSections.put(unitSize << 8, 32);
		maxSizeToSections.put(unitSize << 9, 36);
		maxSizeToSections.put(unitSize << 10, 40);
		maxSizeToSections.put(unitSize << 11, 44);
		maxSizeToSections.put(unitSize << 12, 48);*/
	}

	@Override
	public int createSection(List<Section> secList) throws SectionCreationException {
		if(!foundNumSections){
			long size = secList.get(0).getSize();
			for(long key: maxSizeToSections.keySet()){
				if(size > key){
					MAX_SECTIONS = maxSizeToSections.get(key);
					MAX_CONCURRENT_SOCKETS = MAX_SECTIONS / 4;
				}
			}
			foundNumSections = true;
		}
		
		// verify the maximum sections
		if(secList.size() >= MAX_SECTIONS){
			System.out.println("Maximum sections for this download reached: " + secList.size());
			throw new SectionCreationException();
		}
		
		// check number of active sections
		int numActive = 0;
		for(Section sec: secList){
			if(!sec.isClosed())
				++numActive;
		}
		
		// check the number of concurrent connections
		if(numActive >= MAX_CONCURRENT_SOCKETS){
			System.out.println("Maximum concurrent connections for this download reached: " + secList.size());
			throw new SectionCreationException();
		}
		
		return super.createSection(secList);
	}

}
